#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Predesys Server - Core - Security
@version: 0.2.5
@license: GPL 3.0 (see "license" file)
@author: Jose A. Jimenez
@contact: jajimc@gmail.com"""

import sys
sys.dont_write_bytecode = True
import os
import os.path
DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(os.path.join(DIR, "../errorlog"))
import errorlog
import os
import hashlib
import data
import users

def check_root():
    """Checks if current user is Root. If not, then program exits."""
    # Check user
    id = os.getuid()
    if id != 0:
        exit("Need root privileges to run")
    
def check_user_identity(userId, userPassword):
    """Checks if a pair user ID-user password is valid.
    @param userId: User ID
    @type userId: C{str}
    @param userPassword: User password
    @type userPassword: C{str}
    @return: *True* if user ID and user password are valid. *False* in other case.
    @rtype: C{bool}"""
    if userId == None or (type(userId) != str and type(userId) != unicode) or userId == "":
        raise coreexceptions.ValueNotValidException("'userId' must be a not null and not empty string")
    if userPassword == None or (type(userPassword) != str and type(userPassword) != unicode) or userPassword == "":
        raise coreexceptions.ValueNotValidException("'userPassword' must be a not null and not empty string")
        
    # To prevent SQL injection
    if userId != filter_arg(userId) or userPassword != filter_arg(userPassword): return False
    
    try:
        dbConnection = data.open_connection()
        statement = "select * from users where id='%s' and passwd='%s';" % (userId, get_md5_sum(userPassword))
        result = data.execute(dbConnection, statement)
        row = result.fetchone()
        result.close()
        data.close_connection(dbConnection)
    except Exception as exc:
        errorlog.log_exception(exc.args[0], "predesys-server.core.security.check_user_identity")
        raise
    
    return (row != None)
    
def check_service_execution_permission(userId, serviceId):
    """Checks if a user has privileges to run a given service.
    @param userId: User ID
    @type userId: C{str}
    @param serviceId: Service ID
    @type serviceId: C{str}
    @return: *True* if user has privileges to run the service. *False* in other case.
    @rtype: C{bool}"""
    if userId == None or (type(userId) != str and type(userId) != unicode) or userId == "":
        raise coreexceptions.ValueNotValidException("'userId' must be a not null and not empty string")
    if serviceId == None or (type(serviceId) != str and type(serviceId) != unicode) or serviceId == "":
        raise coreexceptions.ValueNotValidException("'serviceId' must be a not null and not empty string")
        
    # To prevent SQL injection
    if userId != filter_arg(userId) or serviceId != filter_arg(serviceId): return False
        
    if not users.is_user(userId): return False
    else: userGroupId = users.get_user_data(userId).get_group().get_id()
    if userGroupId == None or userGroupId == "": return False
        
    try:
        dbConnection = data.open_connection()
        statement = "select * from service_permissions where service_id='%s' and user_group_id='%s';" % (serviceId, userGroupId)
        result = data.execute(dbConnection, statement)
        row = result.fetchone()
        result.close()
        data.close_connection(dbConnection)
    except Exception as exc:
        errorlog.log_exception(exc.args[0], "predesys-server.core.security.check_service_execution_permission")
        raise
    
    return (row != None)

def get_md5_sum(text):
    """Gets the MD5 checksum of a given text.
    @param text: The text
    @type text: C{str}
    @return: MD5 checksum of text
    @rtype: C{str}"""
    if text == None or type(text) != str: raise coreexceptions.ValueNotValidException("'text' must be a not null string")
    return hashlib.md5(text).hexdigest()
    
# To prevent SQL injection  
def filter_arg(text):
    """Removes some characters from a text to prevent SQL injection.
    @param text: The text
    @type text: C{str}
    @return: Filtered text
    @rtype: C{str}"""
    if text == None or (type(text) != str and type(text) != unicode): raise coreexceptions.ValueNotValidException("'text' must be a not null string")
    return text.replace("'", "").replace("\"", "").replace("=", "").replace(" ", "")
